﻿using Microsoft.SqlServer.Server;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data.SqlTypes;
using System.IO;
using System.Net;
using System.Text;

public partial class Grunndatakvalitet
{
    [Microsoft.SqlServer.Server.SqlFunction]
    public static string HelloWorld()
    {
        return "Hello yourself!";
    }
    [Microsoft.SqlServer.Server.SqlProcedure]
    public static int Http_Method(string sUri, string sMethod, string sProtocolVersion, string sRequestHeaders, string sContentType, byte[] baRequestContent, out string sResponseHeaders, out string sResponseContent)
    {
        return Grunndatakvalitet_Sql_Altinn.Http.Method(sUri, sMethod, sProtocolVersion, sRequestHeaders, sContentType, baRequestContent, out sResponseHeaders, out sResponseContent);
    }
    [Microsoft.SqlServer.Server.SqlFunction]
    public static string Http_SimpleGet(string sUri)
    {
        return new StreamReader(new WebClient().OpenRead(sUri)).ReadToEnd();
    }
    [SqlFunction(FillRowMethodName = "Http_GetRowsAndFields10_Fill")]
    public static IEnumerator Http_SimpleGetRowsAndFields10(string sUri, string sHeaders, string sRowTag, string sColTags)
    {
        return Grunndatakvalitet_Sql_Altinn.Http_SimpleGetRowsAndFields10(sUri, sHeaders, sRowTag, sColTags);
    }
    [SqlFunction(FillRowMethodName = "Http_GetRowsAndFields10_Fill")]
    public static IEnumerator Text_SimpleGetRowsAndFields10(string sContent, string sRowTag, string sColTags)
    {
        return Grunndatakvalitet_Sql_Altinn.Text_SimpleGetRowsAndFields10(sContent, sRowTag, sColTags);
    }
    public static void Http_GetRowsAndFields10_Fill(object row, out Int64 pk, out SqlString headers, out SqlString s0, out SqlString s1, out SqlString s2, out SqlString s3, out SqlString s4, out SqlString s5, out SqlString s6, out SqlString s7, out SqlString s8, out SqlString s9)
    {
        Grunndatakvalitet_Sql_Altinn.Http_GetRowsAndFields10_Fill(row, out pk, out headers, out s0, out s1, out s2, out s3, out s4, out s5, out s6, out s7, out s8, out s9);
    }
    [Microsoft.SqlServer.Server.SqlFunction]
    public static SqlString ExtractFieldValue(string sRowTag, string sColTag)
    {
        return Grunndatakvalitet_Sql_Altinn.ExtractFieldValue(sRowTag, sColTag);
    }
}

public partial class Grunndatakvalitet_Sql_Altinn
{
    public static IEnumerator Http_SimpleGetRowsAndFields10(string sUri, string sHeaders, string sRowTag, string sColTags)
    {
        if (sUri == null || sUri == "")
            yield return new GetRowsAndFields_Row(sColTags);
        else
        { // Read content....
            string sResponseHeaders;
            Stream strContent;
            int iRes = Http.Method(sUri, "GET", "HTTP/1.1", sHeaders, null, null, out sResponseHeaders, out strContent);
            IEnumerator ie = SimpleGetRowsAndFields10(strContent, sResponseHeaders, sRowTag, sColTags);
            while (ie.MoveNext())
                yield return ie.Current;
        }
    }
    public static IEnumerator Text_SimpleGetRowsAndFields10(string sContent, string sRowTag, string sColTags)
    {
        if (sContent == null || sContent == "")
            yield return new GetRowsAndFields_Row(sColTags);
        else
        { // Read content....
            IEnumerator ie = SimpleGetRowsAndFields10(new MemoryStream(Encoding.UTF8.GetBytes(sColTags)), sContent.Length.ToString(), sRowTag, sColTags);
            while (ie.MoveNext())
                yield return ie.Current;
        }
    }
    public static IEnumerator SimpleGetRowsAndFields10(Stream strContent, string sStreamInfo, string sRowTag, string sColTags)
    {
        StreamReader srContent = new StreamReader(strContent);
        if (sRowTag == null || sRowTag == "")
        #region Return all data
        { // Return all data
            GetRowsAndFields_Row row = new GetRowsAndFields_Row("content", sStreamInfo);
            row.SetValues(new string[] { srContent.ReadToEnd() });
            yield return row;
        }
        #endregion Return all data
        else if (sColTags == null || sColTags == "")
        #region Return rows
        {
            GetRowsAndFields_Row row = new GetRowsAndFields_Row("row", sStreamInfo);
            yield return row;
            foreach (string sRow in row.FromStream(srContent, sRowTag))
            {
                row.SetValues(new string[] { sRow });
                yield return row;
            }
        }
        #endregion Return rows
        else if (sColTags == "get tags")
        #region Return tags
        {
            GetRowsAndFields_Row row = new GetRowsAndFields_Row("tags|sql_metadata_create|sql_find_len", sStreamInfo);
            yield return row;
            List<string> lsFields = new List<string>();
            foreach (string sRow in row.FromStream(srContent, sRowTag))
                foreach (string sTag in row.TagsFound(sRow))
                    if (lsFields.IndexOf(sTag) == -1)
                        lsFields.Add(sTag);
            string[] saFields = lsFields.ToArray();
            row.SetValues(new string[]{string.Join("|", saFields)
                ,"SELECT TOP 0 pk=0,headers='', " + string.Join("=CAST('' AS NVARCHAR(MAX)), ", saFields) + "=CAST('' AS NVARCHAR(MAX))"
                ,"SELECT RowCount=COUNT(*), " + string.Join("__len=MAX(LEN(sN)), ", saFields) + "__len=MAX(LEN(sN)) FROM s.f(x)"
                });
            yield return row;
        }
        #endregion Return tags
        else
        #region Return xml as rows and columns
        {
            GetRowsAndFields_Row row = new GetRowsAndFields_Row(sColTags, sStreamInfo);
            foreach (string sRow in row.FromStream(srContent, sRowTag))
            {
                row.SetValues(sRow);
                yield return row;
            }
        }
        #endregion Return xml as rows and columns
    }
    public static SqlString ExtractFieldValue(string sRowTag, string sColtag)
    {
        return GetRowsAndFields_Row.ExtractFieldValue(sRowTag, sColtag);
    }   
    public class Http
    {
        private string SomeFunct()
        {
            #region HTTP
            WebClient client = new WebClient();
            client.Headers["Content-type"] = "application/json";
            MemoryStream ms = new MemoryStream(/*data*/);
            byte[] dataGet = client.DownloadData("http://localhost:49193/Contacts.svc/GetAll");
            byte[] dataAdd = client.UploadData("http://localhost:49193/Contacts.svc/Add", "ADD", ms.ToArray());
            client.UploadData("http://localhost:49193/Contacts.svc/Update", "PUT", ms.ToArray());
            byte[] dataDelete = client.UploadData("http://localhost:49193/Contacts.svc/Delete", "DELETE", ms.ToArray());
            #endregion
            return "";
        }

        public static int Method(string sUri, string sMethod, string sProtocolVersion, string sRequestHeaders, string sContentType, byte[] baRequestBody, out string sResponseHeaders, out string sResponseContent)
        {
            Stream strResponseContent;
            int iRes = Method(sUri, sMethod, sProtocolVersion, sRequestHeaders, sContentType, baRequestBody, out sResponseHeaders, out strResponseContent);
            sResponseContent = new StreamReader(strResponseContent).ReadToEnd();
            return iRes;
        }

        public static int Method(string sUri, string sMethod, string sProtocolVersion, string sRequestHeaders, string sContentType, byte[] baRequestBody, out string sResponseHeaders, out Stream strResponseContent)
        {
            var request = (HttpWebRequest)WebRequest.Create(sUri);
            request.Method = sMethod;
            request.ProtocolVersion = HttpVersion.Version10;
            if (sProtocolVersion != null && sProtocolVersion.IndexOf("1.1") > -1)
                request.ProtocolVersion = HttpVersion.Version11;
            request.ContentType = "text/xml";
            if (sContentType != null && sContentType.Length > 0)
                request.ContentType = sContentType;
            if (baRequestBody != null && baRequestBody.Length > 0)
            {
                request.ContentLength = baRequestBody.Length;
                Stream dataStream = request.GetRequestStream();
                dataStream.Write(baRequestBody, 0, baRequestBody.Length);
                dataStream.Close();
            }

            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            sResponseHeaders = response.Headers.ToString();

            strResponseContent = response.GetResponseStream();
            return (int)response.StatusCode;
        }
    }
    public class GetRowsAndFields_Row
    {
        protected string[] sColNames;
        protected SqlString[] sColValues;
        public Int64 pk;
        public string headers;
        public GetRowsAndFields_Row(string sColTags)
        {
            pk = 0;
            if (sColTags == null)
                sColNames = new string[0];
            else
                sColNames = sColTags.Split("|".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
            sColValues = new SqlString[sColNames.Length];
            for (int i = 0; i < sColNames.Length; i++)
                sColValues[i] = new SqlString(sColNames[i]); // Row "0" has values=names for "hellow world" etc
        }

        public GetRowsAndFields_Row(string sColTags, string headers)
            : this(sColTags)
        {
            this.headers = headers;
        }
        public SqlString GetColValue(int i)
        {
            if (i < sColNames.Length)
                return sColValues[i];
            return SqlString.Null;
        }
        public void SetValues(string [] slValues)
        {
            sColValues = new SqlString[slValues.Length];
            for (int i = 0; i < slValues.Length; i++)
                sColValues[i] = new SqlString(slValues[i]); // Fill row with values
        }
        public bool SetValues(string sRowTag)
        {
            if (sColValues.Length == 0)
            {
                sColValues = new SqlString[] { sRowTag }; // One value
                sColNames = new string[] { "Content" };
                return true;
            }
            else // all values
            {
                ++pk;
                for (int i = 0; i < sColValues.Length; i++)
                    sColValues[i] = ExtractFieldValue(sRowTag, sColNames[i]);
                for (int i = 0; i < sColValues.Length; i++)
                    if (sColValues[i] != SqlString.Null)
                        return true;
            }
            return false;
        }
        public static SqlString ExtractFieldValue(string sRowTag, string sColTag)
        {
            SqlString sRes = SqlString.Null;
            int iTagStart = sRowTag.IndexOf("<" + sColTag);
            if (iTagStart >= 0)
            {
                iTagStart = sRowTag.IndexOf('>', iTagStart) + 1;
                if (iTagStart > 0)
                { // After <Tag>
                    int iTagEnd = sRowTag.IndexOf("</" + sColTag + ">", iTagStart + 1);
                    if (iTagEnd > 0) // Found embedded
                        sRes = new SqlString(sRowTag.Substring(iTagStart, iTagEnd - iTagStart).Trim(" \n".ToCharArray()));
                }
            }
            return sRes;
        }

        public IEnumerable<string> FromStream(StreamReader srContent, string sRowtag)
        {
            // Read to "<ServiceMetaData"
            return srContent.ReadToEnd().Split(new string[] { "</" + sRowtag + ">" }, StringSplitOptions.RemoveEmptyEntries);
        }

        public IEnumerable<string> TagsFound(string sRow)
        { // Return all end tags :)
            int i = sRow.IndexOf("</");
            while (i > -1)
            {
                int iEnd = sRow.IndexOf('>', i + 1);
                if (iEnd == -1)
                    break; // End of tag not found
                yield return sRow.Substring(i + 2, iEnd - i - 2); // abc</x> (3,6) -> (5,1
                i = sRow.IndexOf("</", i + 1);
            }
        }
    }
    public static void Http_GetRowsAndFields10_Fill(object row, out Int64 pk, out SqlString headers, out SqlString s0, out SqlString s1, out SqlString s2, out SqlString s3, out SqlString s4, out SqlString s5, out SqlString s6, out SqlString s7, out SqlString s8, out SqlString s9)
    {
        GetRowsAndFields_Row r = (GetRowsAndFields_Row)row;
        pk = r.pk;
        headers = r.headers;
        s0 = r.GetColValue(0);
        s1 = r.GetColValue(1);
        s2 = r.GetColValue(2);
        s3 = r.GetColValue(3);
        s4 = r.GetColValue(4);
        s5 = r.GetColValue(5);
        s6 = r.GetColValue(6);
        s7 = r.GetColValue(7);
        s8 = r.GetColValue(8);
        s9 = r.GetColValue(9);
    }
}